home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / srcuc.zip / FUTURES.H < prev    next >
C/C++ Source or Header  |  1990-06-20  |  8KB  |  227 lines

  1. /* -*-C-*-
  2.  
  3. $Header: futures.h,v 9.27 90/06/20 17:40:37 GMT cph Exp $
  4.  
  5. Copyright (c) 1987, 1988, 1989, 1990 Massachusetts Institute of Technology
  6.  
  7. This material was developed by the Scheme project at the Massachusetts
  8. Institute of Technology, Department of Electrical Engineering and
  9. Computer Science.  Permission to copy this software, to redistribute
  10. it, and to use it for any purpose is granted, subject to the following
  11. restrictions and understandings.
  12.  
  13. 1. Any copy made of this software must include this copyright notice
  14. in full.
  15.  
  16. 2. Users of this software agree to make their best efforts (a) to
  17. return to the MIT Scheme project any improvements or extensions that
  18. they make, so that these may be included in future releases; and (b)
  19. to inform MIT of noteworthy uses of this software.
  20.  
  21. 3. All materials developed as a consequence of the use of this
  22. software shall duly acknowledge such use, in accordance with the usual
  23. standards of acknowledging credit in academic research.
  24.  
  25. 4. MIT has made no warrantee or representation that the operation of
  26. this software will be error-free, and MIT is under no obligation to
  27. provide any services, by way of maintenance, update, or otherwise.
  28.  
  29. 5. In conjunction with products arising from the use of this material,
  30. there shall be no use of the name of the Massachusetts Institute of
  31. Technology nor of any adaptation thereof in any advertising,
  32. promotional, or sales literature without prior written consent from
  33. MIT in each case. */
  34.  
  35. /* This file contains macros useful for dealing with futures */
  36.  
  37. /* NOTES ON FUTURES, derived from the rest of the interpreter code
  38.  
  39.    ASSUMPTION: The syntaxer is hereby assumed NEVER to generate primitive
  40.    combinations unless the primitive itself is output in the code stream.
  41.    Therefore, we don't have to explicitly check here that the expression
  42.    register has a primitive in it.
  43.  
  44.    ASSUMPTION: The SYMBOL slot of a VARIABLE does NOT contain a future, nor
  45.    do the cached lexical address slots.
  46.  
  47.    ASSUMPTION: Environment structure, which is created only by the
  48.    interpreter, never contains FUTUREs on its spine.
  49.  
  50.    ASSUMPTION: History objects are never created using futures.
  51.  
  52.    ASSUMPTION: State points, which are created only by the interpreter,
  53.    never contain FUTUREs except possibly as the thunks (which are handled
  54.    by the apply code).
  55.  
  56.    OPTIMIZATIONS (?):
  57.    After a lot of discussion, we decided that variable reference will check
  58.    whether a value stored in the environment is a determined future which
  59.    is marked spliceable.  If so, it will splice out the future from the
  60.    environment slot to speed up subsequent references.
  61.  
  62.    EQ? does a normal identity check and only if this fails does it touch the
  63.    arguments.  The same thing does not speed up MEMQ or ASSQ in the normal
  64.    case, so it is omitted there.
  65.  
  66.    The following are NOT done, but might be useful later
  67.    (1) Splicing on SET! operations
  68.    (2) Splicing at apply and/or primitive apply
  69.    (3) Splicing all arguments when a primitive errors on any of them
  70.    (4) Splicing within the Arg_n_Type macro rather than after longjmping
  71.        to the error handler.
  72.  
  73.    KNOWN PROBLEMS:
  74.    (1) Garbage collector should be modified to splice out futures.  DONE.
  75.  
  76.    (2) Purify should be looked at and we should decide what to do about
  77.        purifying an object with a reference to a future (it should probably
  78.        become constant but not pure).
  79.  
  80.    (3) Look at Impurify and Side-Effect-Impurify to see if futures
  81.        affect them in any way. */
  82.  
  83. /* Data structure definition */
  84.  
  85. /* The IS_DETERMINED slot has one of the following type of values:
  86.     #F    if the value is not yet known;
  87.     #T    if the value is known and the garbage collector is free
  88.       to remove the future object in favor of its value everywhere;
  89.    else    the value is known, but the GC must leave the future object. */
  90.  
  91. #define FUTURE_VECTOR_HEADER    0
  92. #define FUTURE_IS_DETERMINED    1
  93. #define FUTURE_LOCK             2
  94. #define FUTURE_VALUE        3    /* if known, else */
  95. #define FUTURE_QUEUE        3    /* tasks waiting for value */
  96. #define FUTURE_PROCESS        4
  97. #define FUTURE_STATUS        5
  98. #define FUTURE_ORIG_CODE    6
  99. #define FUTURE_PRIVATE        7
  100. #define FUTURE_WAITING_ON    8
  101. #define FUTURE_METERING        9
  102. #define FUTURE_USER        10
  103.  
  104. #define Future_Is_Locked(P)                        \
  105.   ((MEMORY_REF ((P), FUTURE_LOCK)) != SHARP_F)
  106.  
  107. #define Future_Has_Value(P)                        \
  108.   ((MEMORY_REF ((P), FUTURE_IS_DETERMINED)) != SHARP_F)
  109.  
  110. #define Future_Value(P)                            \
  111.   (MEMORY_REF ((P), FUTURE_VALUE))
  112.  
  113. #define Future_Spliceable(P)                        \
  114.   (((MEMORY_REF ((P), FUTURE_IS_DETERMINED)) == SHARP_T) &&        \
  115.    ((MEMORY_REF ((P), FUTURE_LOCK)) == SHARP_F))
  116.  
  117. #define Future_Is_Keep_Slot(P)                        \
  118.   (! (BOOLEAN_P (MEMORY_REF ((P), FUTURE_IS_DETERMINED))))
  119.  
  120. #ifndef COMPILE_FUTURES
  121.  
  122. #define TOUCH_IN_PRIMITIVE(P, To_Where) To_Where = (P)
  123. #define TOUCH_SETUP(object) Microcode_Termination (TERM_TOUCH)
  124. #define Log_Touch_Of_Future(F) {}
  125. #define Call_Future_Logging()
  126. #define Must_Report_References() (false)
  127. #define FUTURE_VARIABLE_SPLICE(P, Offset, Value)
  128.  
  129. #else /* COMPILE_FUTURES */
  130.  
  131. /* TOUCH_IN_PRIMITIVE is used by primitives which are not
  132.    strict in an argument but which touch it none the less. */
  133.  
  134. #define TOUCH_IN_PRIMITIVE(P, To_Where)                    \
  135. {                                    \
  136.   SCHEME_OBJECT Value = (P);                        \
  137.   while (FUTURE_P (Value))                        \
  138.     {                                    \
  139.       if (Future_Has_Value (Value))                    \
  140.     {                                \
  141.       if (Future_Is_Keep_Slot (Value))                \
  142.         {                                \
  143.           Log_Touch_Of_Future (Value);                \
  144.         }                                \
  145.       Value = (Future_Value (Value));                \
  146.     }                                \
  147.       else                                \
  148.     {                                \
  149.       Val = Value;                            \
  150.       PRIMITIVE_ABORT (PRIM_TOUCH);                    \
  151.     }                                \
  152.     }                                    \
  153.   (To_Where) = Value;                            \
  154. }
  155.  
  156. #define TOUCH_SETUP(object)                        \
  157. {                                    \
  158.   Save_Cont ();                                \
  159.  Will_Push (STACK_ENV_EXTRA_SLOTS + 2);                    \
  160.   STACK_PUSH (object);                            \
  161.   STACK_PUSH (Get_Fixed_Obj_Slot (System_Scheduler));            \
  162.   STACK_PUSH (STACK_FRAME_HEADER + 1);                    \
  163.  Pushed ();                                \
  164. }
  165.  
  166. #define FUTURE_VARIABLE_SPLICE(P, Offset, Value)            \
  167. {                                    \
  168.   while ((FUTURE_P (Value)) && (Future_Spliceable (Value)))        \
  169.     {                                    \
  170.       Value = (Future_Value (Value));                    \
  171.       MEMORY_SET (P, Offset, Value);                    \
  172.     }                                    \
  173. }
  174.  
  175. #ifdef FUTURE_LOGGING
  176.  
  177. #define Touched_Futures_Vector() (Get_Fixed_Obj_Slot (Touched_Futures))
  178.  
  179. #define Logging_On()                            \
  180.   ((Valid_Fixed_Obj_Vector ()) && (Touched_Futures_Vector ()))
  181.  
  182. /* Log_Touch_Of_Future adds the future which was touched to the vector
  183.    of touched futures about which the scheme portion of the system has
  184.    not yet been informed. */
  185.  
  186. #define Log_Touch_Of_Future(F)                        \
  187. {                                    \
  188.   if (Logging_On ())                            \
  189.     {                                    \
  190.       SCHEME_OBJECT TFV = (Touched_Futures_Vector ());            \
  191.       long Count =                            \
  192.     ((UNSIGNED_FIXNUM_TO_LONG (VECTOR_REF (TFV, 0))) + 1);        \
  193.       (VECTOR_REF (TFV, 0)) = (LONG_TO_UNSIGNED_FIXNUM (Count));    \
  194.       if (Count < (VECTOR_LENGTH (TFV)))                \
  195.     (VECTOR_REF (TFV, Count)) = (OBJECT_NEW_TYPE (TC_VECTOR, F));    \
  196.     }                                    \
  197. }
  198.  
  199. /* Call_Future_Logging calls a user defined scheme routine if the vector
  200.    of touched futures has a nonzero length. */
  201.  
  202. #define Must_Report_References()                    \
  203.   ((Logging_On ()) &&                            \
  204.    ((UNSIGNED_FIXNUM_TO_LONG                        \
  205.      (VECTOR_REF ((Touched_Futures_Vector ()), 0)))            \
  206.     > 0))
  207.  
  208. #define Call_Future_Logging()                        \
  209. {                                    \
  210.  Will_Push (STACK_ENV_EXTRA_SLOTS + 2);                    \
  211.   STACK_PUSH (Touched_Futures_Vector ());                \
  212.   STACK_PUSH (Get_Fixed_Obj_Slot (Future_Logger));            \
  213.   STACK_PUSH (STACK_FRAME_HEADER + 1);                    \
  214.  Pushed ();                                \
  215.   (Touched_Futures_Vector ()) = SHARP_F;                \
  216.   goto Apply_Non_Trapping;                        \
  217. }
  218.  
  219. #else /* not FUTURE_LOGGING */
  220.  
  221. #define Log_Touch_Of_Future(F) {}
  222. #define Call_Future_Logging()
  223. #define Must_Report_References() (false)
  224.  
  225. #endif /* FUTURE_LOGGING */
  226. #endif /* COMPILE_FUTURES */
  227.